<?php

namespace App\Http\Service\agents;

use App\Http\Controllers\Admin\Traits\AdminTrait;
use App\Models\Admin\Company;
use App\Models\Admin\Setting;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use App\Models\Admin\AdminRegion;
use App\Http\Service\BaseService;
use App\Exceptions\CdjException;
use App\Exceptions\ApiException;
use App\Models\Admin\Agents;
use App\Models\Admin\User;
use App\Org\Dns;


class AgentsService extends BaseService
{
    use AdminTrait;
    public $operateData;
    public $agentModel;
    public $action;

    public $token;
    public $agentInfo;

    public function __construct(Agents $agentModel)
    {
        parent::__construct();
        $this->agentModel = $agentModel;
    }

    private function checkNoPassData($params)
    {
        $rules = [
            'user_id'  => 'required|numeric',
            'agent_id' => 'required|numeric',
        ];

        $validator = Validator::make($params, $rules);
        if ($validator->fails())
            throw new CdjException($validator->errors()->first(), 40001);

        $user_id = $params['user_id'];
        $agentId = $params['agent_id'];
        $user    = User::where('company_id', $agentId)->where('id', $user_id)->first();
        if (!$user)
            throw new CdjException('管理员不存在', 40002);

        $this->agentInfo = Agents::select('id', 'agent_name', 'domain_name')->find($agentId);
        if (!$this->agentInfo->domain_name)
            throw new CdjException('客户未设置域名', 40002);

        $this->token = Auth::guard('company')->login($user, true);
        if (!$this->token)
            throw new CdjException('token获取失败', 40002);

        return true;
    }

    /**
     * @param 代理商免密登录
     * @param array $id
     * @return array
     * @throws CdjException
     */
    public function getLoginAgentNoPassUrl($params)
    {
        // 数据检测
        $this->checkNoPassData($params);

        //记录日志
        Company::addLog($this->agentInfo->getOriginal(), [], 6, __FUNCTION__);

        $domainNameArr = explode(',', $this->agentInfo->domain_name);
        $url           = 'http://' . $domainNameArr[0] . '/cadmin';
        return [
            'url'   => $url,
            'token' => 'Bearer ' . $this->token,
        ];
    }

    private function checkPasswordAgentData($params)
    {
        //过滤数据
        $rule      = [
            'user_id'  => 'required|exists:users,id',
            'password' => 'required',
        ];
        $validator = Validator::make($params, $rule);
        if ($validator->fails())
            throw new CdjException($validator->errors()->first(), 40001);

        $info = User::find($params['user_id']);
        if (!$info)
            throw new CdjException('用户信息不存在', 40001);

        return true;
    }

    /**
     * @param 修改密码
     * @param array $id
     * @return array
     * @throws CdjException
     */
    public function changePasswordAgentAdmin($params)
    {
        // 数据检测
        $this->checkPasswordAgentData($params);

        $user_id = $params['user_id'];
        DB::beginTransaction();
        try {
            $password       = Hash::make($params['password']);
            $info           = User::find($user_id);
            $perInfo        = $info->getOriginal();     // 获取修改之前的字段
            $info->password = $password;
            $info->save();

            // 添加日志
            $nextInfo = $info->getChanges();            // 获取修改之后的字段
            User::addLog($perInfo, $nextInfo, 6, __FUNCTION__);
            DB::commit();

            return true;
        } catch (\Exception $e) {
            DB::rollBack();

            throw new CdjException($e->getMessage(), 50001);
        }
    }

    /**
     * @param 代理商管理员列表
     * @param array $id
     * @return array
     * @throws CdjException
     */
    public function getAgentAdminUsers($params)
    {
        $rule      = [
            'agent_id' => 'required|exists:agents,id'
        ];
        $validator = Validator::make($params, $rule);
        if ($validator->fails())
            throw new CdjException($validator->errors()->first(), 40001);

        $params['role_id']    = 1;
        $params['company_id'] = $params['agent_id'];
        $list                 = User::getList($params);

//        dd(DB::getQueryLog());
        return $list;
    }

    /**
     * @param 代理商列表
     * @param array $id
     * @return array
     * @throws CdjException
     */
    public function getList($params)
    {
        return Agents::list($params);
    }

    /**
     * @param 代理商详情
     * @param array $id
     * @return array
     * @throws CdjException
     */
    public function getDetail($params)
    {
        if (!isset($params['id']) && !$params['id']) {
            throw new CdjException('代理商ID不能为空', 40001);
        }

        $info = Agents::where('id', $params['id'])->first();
        if (!$info)
            throw new CdjException('代理商信息不存在', 40002);

//        AdminRegion::setJsonFile();

        return $info;
    }

    /**
     * @desc 数据处理
     * @param array $params
     * @return array
     * @throws CdjException
     */
    public function handler($params)
    {
        $this->action = $params['action'] ?? 'forbidden';
        switch ($this->action) {
            case "add":
            case "update":
                // 校验,完善入库数据
                $this->checkFillData($params);
                // 入库数据
                $this->storageData();

                // ToDo...
                break;
            // 审核
            case "audit":
                // 资质审核
                $this->setAuditData($params);
                // ToDo...
                break;
            case "del":
                // ToDo...
                break;
            default:
                throw new CdjException('非法操作', 50001);
        }

        return ['id' => $this->operateData['id'] ?? $params['id']];
    }

    private function setAuditData($params)
    {
        $rules = [
            'id'           => 'required|numeric',
            'audit_status' => 'required|numeric',
        ];

        $validator = Validator::make($params, $rules);
        if ($validator->fails())
            throw new CdjException($validator->errors()->first(), 40001);

        $info = Agents::where('id', $params['id'])->first();
        if (!$info)
            throw new CdjException('代理商信息不存在', 40002);

        $unixTime          = time();
        $this->operateData = [
            'id'           => $params['id'],
            'audit_remark' => $params['audit_remark'] ?? '',
            'audit_status' => $params['audit_status'],
            'updated_at'   => $unixTime,
        ];

        return Agents::where('id', $params['id'])->update($this->operateData);
    }

    private function checkFillData($params)
    {
        $rules = [
            'agent_name'    => 'required|string',
            'manager_name'  => 'required|string',
            'mobile'        => 'required|digits:11',
            'domain_name'   => 'required|string',
            'province_code' => 'required|numeric',
            'city_code'     => 'required|numeric',
            'country_code'  => 'required|numeric',
            'address'       => 'required|string',
        ];

        if (in_array($params['action'], ['del', 'update', 'audit']))
            $rules['id'] = 'required|numeric';

        $validator = Validator::make($params, $rules);
        if ($validator->fails())
            throw new CdjException($validator->errors()->first(), 40001);

        if ($this->action != 'add' && isset($params['id']) && $params['id']) {
            $info = Agents::where('id', $params['id'])->first();
            if (!$info)
                throw new CdjException('代理商信息不存在', 40002);
        }

        $info = Agents::where($this->formatWhere($params, 'agent_name'))->first();
        if ($info)
            throw new CdjException('代理商名称已存在', 40002);

        $info = Agents::where($this->formatWhere($params, 'mobile'))->first();
        if ($info)
            throw new CdjException('负责人手机号已存在', 40002);

        $info = Agents::where($this->formatWhere($params, 'domain_name'))->count();
        if ($info)
            throw new CdjException('域名已存在', 40002);

        // 检测域名是否已解析
        $isExists = $this->domainIsExists($params['domain_name']);
        if (!$isExists)
            throw new CdjException('域名还未解析，请添加域名解析', 40002);

        $unixTime          = time();
        $this->operateData = [
            'id'             => ($this->action != 'add' && $params['id']) ? $params['id'] : 0,
            'qualifications' => $params['qualifications'] ?? '',
            'agent_name'     => $params['agent_name'],
            'manager_name'   => $params['manager_name'],
            'domain_name'    => $params['domain_name'],
            'province_code'  => $params['province_code'],
            'city_code'      => $params['city_code'],
            'country_code'   => $params['country_code'],
            'address'        => $params['address'],
            'mobile'         => $params['mobile'],
            'status'         => 1,
            'updated_at'     => $unixTime,
        ];

        if ($this->action == 'add')
            $this->operateData['created_at'] = $unixTime;

        return $this->operateData;
    }

    private function formatWhere($params, $column)
    {
        $whereArr = [[$column, '=', "{$params[$column]}"]];
        if ($this->action != 'add' && isset($params['id']) && $params['id']) {
            array_push($whereArr, ['id', '!=', $params['id']]);
        }

        return $whereArr;
    }

    private function storageData()
    {
        // 开启事务
        DB::beginTransaction();
        try {
            // 数据入库
            switch ($this->action) {
                case 'update':
                    $info = Agents::where('id', $this->operateData['id'])->first();
                    Agents::where('id', $this->operateData['id'])->update($this->operateData);
                    break;
                case 'add':
                    $info = Agents::create($this->operateData);
                    break;
                default:
                    break;
            }
            $this->operateData['id'] = $info->id;

            // 首次创建生成默认管理员
            if ($this->action == 'add' && $this->operateData['id']) {
                $password  = Hash::make($this->operateData['mobile']);
                $user_data = [
                    'name'       => $this->operateData['manager_name'],
                    'email'      => $this->operateData['email'] ?? '',
                    'password'   => $password,
                    'mobile'     => $this->operateData['mobile'],
                    'role_id'    => 1,
                    'username'   => 'admin',
                    'company_id' => $this->operateData['id'],
                    'status'     => 1,
                ];
                User::create($user_data);
            }

            //生成默认配置
            $set_data = [
                'agent_id'   => $this->operateData['id'],
                'site_title' => $this->operateData['agent_name'],
            ];
            Setting::add($set_data);

            // 添加操作日志
            $opType = ['add' => 1, 'update' => 2, 'del' => 3];
            if (method_exists($this->agentModel, 'addLog')) {
                $this->agentModel->addLog($info, [], $opType[$this->action]);
            }

            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            throw new CdjException($exception->getMessage(), $exception->getCode());
        }

        return true;
    }
}
